package org.vtradex;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.fastjson.JSON;
import org.vtradex.oms.BaseOrderDetailSnWrite;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 请补充描述信息
 *
 * @author <a href="mailto:panpan.chen@vtradex.com">陈盼盼</a>
 * @version v1.0
 * @since 2023/12/30 21:51
 **/
public abstract class AbstractWrite<T> {

    private BufferedWriter bufferedWriter = null;

    protected abstract String tableName();

    protected abstract Class entityCls();

    public final void toSql(Integer headRows, File source) {
        ExcelReader excelReader = EasyExcel.read(source,
                entityCls(), new AbstractWrite.ExcelListener()).build();
        ReadSheet readSheet = EasyExcel.readSheet(0)
                .headRowNumber(headRows)
                .build();

        excelReader.read(readSheet);
        excelReader.finish();
    }

    public AbstractWrite(BufferedWriter bufferedWriter) {
        this.bufferedWriter = bufferedWriter;
    }

    public static class MyMap extends HashMap {
        @Override
        public Object put(Object key, Object value) {
            if (key instanceof String) {
                key = ((String) key).toUpperCase();
            }
            return super.put(key, value);
        }
    }

    public class ExcelListener extends AnalysisEventListener<T> {
        private Map<Integer, String> headMap;

        //创建list集合封装最终的数据
        List<T> list = new ArrayList<>();

        //一行一行去读取excle内容
        @Override
        public void invoke(T user, AnalysisContext analysisContext) {
            System.out.println("***" + user);

            String jsonString = JSON.toJSONString(user);

            Map map = JSON.parseObject(jsonString, MyMap.class);

            String sql = "insert into " + tableName() + " (%s) values (%s);";

            List<String> keys = new ArrayList<>();
            List<Object> values = new ArrayList<>();

            this.headMap.values().stream().filter(a -> {

                if (!map.containsKey(a)) {
                    return false;
                }
                if (map.get(a) == null) {
                    return false;
                }

                if ("-1".equals(map.get(a).toString())) {
                    return false;
                }
                return true;
            }).forEach(a -> {
                keys.add(a);
//                values.add(map.get(a));
                this.addValue(values, map.get(a));
            });

            sql = String.format(sql, keys.stream().collect(Collectors.joining(",")),
                    values.stream().map(a -> a.toString()).collect(Collectors.joining(","))
            );
            System.out.println(sql);
            try {
                bufferedWriter.write(sql + "\r\n");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        private void addValue(List<Object> values, Object o) {
            if (o instanceof String) {
                values.add("'" + o + "'");
            } else if (o instanceof Date) {
                values.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(o));

            } else if (o instanceof Long || o instanceof Integer) {
                values.add(o);
            } else {
                throw new RuntimeException("未知的类型。" + o.getClass().getTypeName());
            }
        }

        //读取excel表头信息
        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            System.out.println("表头信息：" + headMap);
            this.headMap = headMap;
        }

        //读取完成后执行
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            System.out.println(analysisContext);
            try {
                AbstractWrite.this.bufferedWriter.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
